<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        const bucket = new WeakMap();
        let activeEffect;
        const effectStack = []; //新增
        //原始数据
        const data = {
                text: "hello word",
                text2: "hello2"
            }
            //设置里面的函数抽象到’追踪‘
        function track(target, key) {
            if (!activeEffect) {
                return;
            }
            let depsMap = bucket.get(target);
            if (!depsMap) {
                //用对象来做key
                bucket.set(target, (depsMap = new Map()))
            }
            let deps = depsMap.get(key);
            if (!deps) {
                depsMap.set(key, (deps = new Set()));
            }
            deps.add(activeEffect);
        }
        //设置的代码，抽象到这里
        function trigger(target, key) {

            const depsMap = bucket.get(target);
            if (!depsMap) {
                return;
            }
            const effects = depsMap.get(key);
            effects && effects.forEach(fn => fn());
        }
        const obj = new Proxy(data, {
            get(target, key) {
                track(target, key);
                return target[key]; //返回对应的值
            },
            set(target, key, newVal) {
                target[key] = newVal;
                trigger(target, key);
            }
        })

        //用于注册副作用函数
        function effect(fn) {
			//更新时候，会把收集到副作用函数，执行一遍effectStack
            const effectFn = () => {
                activeEffect = fn;//第一次调动时候是effect函数传进来的fn函数,如果没有嵌套，这行代码是有用的，如果有嵌套，它将会失去作用
                //添加到数组最后
                effectStack.push(effectFn); //函数把自己放到数组里面
				//这个函数里面会再次更改activeEffect，如果不处理的话，查看【代码1】，text还没有触发副作用函数收集，text2的副作用函数收集就触发了
				//如果嵌套无数层，这个函数里面就回触发收集无数次且都没有等待上一次收集完成时候，就触发下一次
                fn();//这个函数里面会导致effectFn，不断的被调用，如果嵌套很多层
                //
                effectStack.pop(); //移除掉数组最后一个
			//	console.log("effectStack",effectStack[0],"fn:::::::",fn)
				//最外层fn是传进来的fn，内层fn是effectFn？
                activeEffect = effectStack[effectStack.length - 1];
            }
            effectFn();

        }
        let tmp1, tmp2;
		//代码1
        effect(() => {
            console.log("更新1")
                //这里需要用到的是proxy对象下的text了，而不是data.text
            effect(() => {
                console.log("更新2")
                    //这里需要用到的是proxy对象下的text了，而不是data.text
                tmp2 = obj.text2;
            });
            tmp1 = obj.text;//【代码①】当这里赋值时候，触发get，会把effectStack队列里面的副作用函数遍历执行一遍！！！！！
        });
        setTimeout(() => {
            //这里需要用到的是proxy对象下的text了，而不是data.text
            obj.text = "hello world???????
            console.log("修改变量")
        }, 1000)
		
		
		//嵌套收集代码类似一下，只是get收集是get的时候并行收集的，并且只收集activeEffect的值
		
		// var effectBuck=[];
		// var activeEffect=null;
		// var effect=(fn=>{
		//     var tmpFn=()=>{
		//         activeEffect=fn;
		//         effectBuck.push(fn)
		//         fn();
		//     }
		//     tmpFn();
		    
		// })
		
		// effect(()=>{
		
		//     effect(()=>{
		    
		//          console.log("嵌套一层")
		//     })
		//     console.log("最外一层")
		// })
		// effectBuck;
    </script>
</body>

</html>